﻿
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;

namespace CatEars.Core.Collections
{
    /// <summary>
    /// 树形结构节点
    /// </summary>
    [DebuggerDisplay("Value={Value} ChildrenCount={Children.Count}")]
    public abstract class TreeNode<T>
    {
        /// <summary>
        /// 初始化
        /// </summary>
        public TreeNode()
        {
        }

        /// <summary>
        /// 初始化，指定值
        /// </summary>
        /// <param name="value">value</param>
        public TreeNode(T value)
        {
            Value = value;
        }

        /// <summary>
        /// 值对象
        /// </summary>
        public T Value { get; set; }

        /// <summary>
        /// 上级节点
        /// </summary>
        public TreeNode<T> Parent { get; protected set; }

        /// <summary>
        /// 子节点(只读 不允许修改)
        /// </summary>
        public abstract ICollection<TreeNode<T>> Children { get; }
        
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="item"></param>
        protected abstract void AddItem(TreeNode<T> item);
        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected abstract bool RemoveItem(TreeNode<T> item);
        /// <summary>
        /// 创建下级集合
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        protected abstract TreeNode<T> CreateInstance(T value);

        /// <summary>
        /// 添加子节点
        /// </summary>
        /// <param name="value">value</param>
        /// <returns>返回值</returns>
        public TreeNode<T> AddChild(T value)
        {
            var newNode = CreateInstance(value);
            newNode.Parent = this;
            AddItem(newNode);
            return newNode;
        }

        /// <summary>
        /// 添加子节点
        /// </summary>
        /// <param name="node">node</param>
        public void AddChild(TreeNode<T> node)
        {
            if (node.Parent != null)
            {
                node.Parent.RemoveChild(node);
            }
            node.Parent = this;
            AddItem(node);
        }

        /// <summary>
        /// 移除该节点
        /// </summary>
        public void Remove()
        {
            if (this.Parent != null)
            {
                this.Parent.RemoveChild(this);
            }
        }

        /// <summary>
        /// 移除子节点
        /// </summary>
        /// <param name="node">node</param>
        /// <returns>是否成功删除</returns>
        public bool RemoveChild(TreeNode<T> node)
        {
            if (node.Parent == this)
            {
                bool blnResult = RemoveItem(node);
                if (blnResult)
                {
                    node.Parent = null;
                }
                return blnResult;
            }
            return false;
        }
    }

    /// <summary>
    /// TreeNode的List实现
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class TreeNodeList<T> : TreeNode<T>
    {
        /// <summary>
        /// 初始化
        /// </summary>
        public TreeNodeList()
        {
        }

        /// <summary>
        /// 初始化，指定值
        /// </summary>
        /// <param name="value">value</param>
        public TreeNodeList(T value)
            : base(value)
        {
        }

        /// <summary>
        /// 子节点
        /// </summary>
        protected List<TreeNode<T>> m_children
            = new List<TreeNode<T>>();

        /// <summary>
        /// 子节点(只读 不允许修改)
        /// </summary>
        public override ICollection<TreeNode<T>> Children
        {
            get
            {
                return m_children;
            }
        }

        /// <summary>
        /// 子节点(只读 不允许修改)
        /// </summary>
        public List<TreeNode<T>> Children2
        {
            get
            {
                return m_children;
            }
        }

        /// <summary>
        /// 创建下级集合
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        protected override TreeNode<T> CreateInstance(T value)
        {
            return new TreeNodeList<T>(value);
        }
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="item"></param>
        protected override void AddItem(TreeNode<T> item)
        {
            m_children.Add(item);
        }
        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected override bool RemoveItem(TreeNode<T> item)
        {
            return m_children.Remove(item);
        }
    }

    /// <summary>
    /// TreeNode的链表实现
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class TreeNodeLinkedList<T> : TreeNode<T>
    {
        /// <summary>
        /// 初始化
        /// </summary>
        public TreeNodeLinkedList()
        {
        }

        /// <summary>
        /// 初始化，指定值
        /// </summary>
        /// <param name="value">value</param>
        public TreeNodeLinkedList(T value)
            : base(value)
        {
        }
        /// <summary>
        /// 子节点
        /// </summary>
        protected LinkedList<TreeNode<T>> m_children
            = new LinkedList<TreeNode<T>>();

        /// <summary>
        /// 子节点(只读 不允许修改)
        /// </summary>
        public override ICollection<TreeNode<T>> Children
        {
            get
            {
                return m_children;
            }
        }

        /// <summary>
        /// 子节点(只读 不允许修改)
        /// </summary>
        public LinkedList<TreeNode<T>> Children2
        {
            get
            {
                return m_children;
            }
        }

        /// <summary>
        /// 创建下级集合
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        protected override TreeNode<T> CreateInstance(T value)
        {
            return new TreeNodeLinkedList<T>(value);
        }
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="item"></param>
        protected override void AddItem(TreeNode<T> item)
        {
            m_children.AddLast(item);
        }
        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected override bool RemoveItem(TreeNode<T> item)
        {
            return m_children.Remove(item);
        }
    }

    /// <summary>
    /// 静态辅助类
    /// </summary>
    public static class TreeNode
    {
        /// <summary>
        /// 前序遍历树节点
        /// </summary>
        /// <param name="root">根节点</param>
        /// <param name="blnOutputRoot">是否输出根节点</param>
        /// <returns>返回值</returns>
        public static IEnumerable<TreeNode<DataRow>> GetAllNodesF(
            TreeNode<DataRow> root,
            bool blnOutputRoot = false)
        {
            if (blnOutputRoot)
            {
                yield return root;
            }
            foreach (var child in root.Children)
            {
                yield return child;
                var childChild = GetAllNodesF(child, false);
                foreach (var child2 in childChild)
                {
                    yield return child2;
                }
            }
        }

        /// <summary>
        /// 后序遍历树节点
        /// </summary>
        /// <param name="root">根节点</param>
        /// <param name="blnOutputRoot">是否输出根节点</param>
        /// <returns>返回值</returns>
        public static IEnumerable<TreeNode<DataRow>> GetAllNodesL(
            TreeNode<DataRow> root,
            bool blnOutputRoot = false)
        {
            foreach (var child in root.Children)
            {
                var childChild = GetAllNodesL(child, false);
                foreach (var child2 in childChild)
                {
                    yield return child2;
                }
                yield return child;
            }
            if (blnOutputRoot)
            {
                yield return root;
            }
        }

        /// <summary>
        /// 从DataTable获取整个树结构
        /// </summary>
        /// <param name="dtSource">数据源</param>
        /// <param name="strIDKey">标识字段名</param>
        /// <param name="strUpIDKey">上级标识字段名</param>
        /// <returns>返回值</returns>
        public static TreeNode<DataRow> LoadFromDataTable(
            DataTable dtSource,
            string strIDKey,
            string strUpIDKey)
        {
            TreeNode<DataRow> root = new TreeNodeLinkedList<DataRow>();
            Dictionary<string, TreeNode<DataRow>> dictKeyToNode
                = new Dictionary<string, TreeNode<DataRow>>();
            foreach (DataRow row in dtSource.Rows)
            {
                var newNode = new TreeNodeLinkedList<DataRow>(row);
                string strKey = row[strIDKey].ToString();
                dictKeyToNode[strKey] = newNode;
            }
            foreach (var node in dictKeyToNode.Values)
            {
                string strUpKey = node.Value[strUpIDKey].ToString();
                TreeNode<DataRow> upNode;
                if (dictKeyToNode.TryGetValue(strUpKey, out upNode))
                {
                    upNode.AddChild(node);
                }
            }
            var rootNodes = dictKeyToNode.Values.Where(t => t.Parent == null);
            foreach (var node in rootNodes)
            {
                root.AddChild(node);
            }
            return root;
        }
    }
}
